這篇繼續 DAY2 的例子,在上篇的結尾,我們對物件導向範型的解法提出了另一項需求:在聽課的人中,研究生中有擔任助教的人必須要先到行政處找行政人員辦理一些業務。面對這項新的需求,我們該如何應對?
現在遇到的問題是除了「一般學生 (RegularStudent) 」之外,還有「研究所學生 (GraduateStudent) 」,面對這項新需求,我們必須讓這兩種學生實體化後能夠都被納入蒐集學生的集合內(物件導向範型的流程 step2)。
解決的方案就是做出一個包含 RegurlarStudent
和 GraduateStudent
的 Student
,我們稱 Student
類別為抽象類別 (Abstract Class)。
這個例子,RegularStudent
是一種 Student
、GraduateStudent
也是一種 Student
。這種關係是繼承 (Inheritance) 中的一種特例,稱作 is-a 關係。
這樣的關係有很多種稱呼方式,我們可以說「GraduateStudent
繼承 Student
」、「GraduateStudent
是 Student
的子類別」等等。
多數人對抽象類別的理解是「不能被實體化的類別」,包括我在還沒讀這本書前,也是這樣子理解。
但本書提到一個有趣的形容方式:
抽象類別可以充當其他類別的「占位符號」(placeholder) 。可以使用抽象類別定義其衍生類別必須實作的方法。
前者是用實作的層次上去看待它;後者則是在概念層次去理解它。
Placeholder 就像是下圖這樣,在網站上填寫一些基本資料的時候 input 裡的暗示你的字,像是在姓名欄位顯示 "Your name" 來告訴你這裡要填名字。
它某種程度規範了你必須要填寫的字(必須實作的method),但你仍然有權力去寫自己想寫的東西(method 實作的行為由衍生類別自己決定)。
本書作者對「多型 (polymorphism) 」的描述如下:
在物件導向語言中,我們經常用抽象類別的參照來參照物件。但是,我們真正參照的是從抽象類別衍生的類別的具體實體。
因此,當我透過抽象參照概念性地要求物件做什麼時,將得到不同的行為,具體行為取決於衍生物件的具體類型。
看起來十分拗口⋯但其實很好理解,從上面學生的例子來說,講師跟同學說「去下間教室」,每位學生會根據類型不同而採取不同的行為。而這個現象就是多型。
可視性源自於物件的特性 —— 物件自己負責自己,也因為如此,很多東西不需要讓其他物件知道。
例如說,學生小明沒有必要把他家狗的名字告訴給講師知道(有可能他家的狗叫 )。null
可視性也可以理解成被其他物件的可存取性,那麼,就會有以下三類:
也因為有些資料元素和 methods 對外是隱藏的,這就引出了「封裝 (encapsulation) 」的概念。封裝就是一種資料隱藏,但其實不僅止於此,它甚至可以指涉各種隱藏。
例如,講師不知道小明到底是一般學生還是研究生。所以學生的類型對講師隱藏了;從物件導向語言來說,抽象類別 Student
隱藏了從其衍生的類別的類型。
封裝給我們的好處有幾點:
建構函數 (constructor) 是物件被建立時一定會被呼叫的一個 method,它負責初始化、設定預設資訊、設定與其他物件關係或建立物件所需的其他工作的天然場所。
相反地,當一個物件不再存在或不需要再被使用到時,就會呼叫一個摧毀該物件的 method,它稱為解構函數(destructor)。
下一篇我將會提到不同類別之間的關係,文章長度不夠的話也許還會提到一些設計模式的簡介(chapter 5)。